﻿namespace PhotobucketNet
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Net;
    using System.Net.Cache;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Xml;

    public class Photobucket
    {
        private const string _addMediaTagMethod = "POST";
        private const string _albumUrl = "album/";
        private string _apiKey;
        private const string _apilogin = "apilogin/";
        private string _apiSecret;
        private const string _apiUrl = "http://api.photobucket.com/";
        private bool _appAuthorized;
        private const string _autotagging = "autotagging";
        private ConsumerToken _consumerToken;
        private const string _contact = "contact";
        private const string _createAlbumMethod = "POST";
        private User _currentUser;
        private const string _defaultimagesize = "defaultimagesize";
        private const string _degrees = "degrees";
        private const string _deleteAlbumMethod = "DELETE";
        private const string _deleteMediaDescriptionMethod = "DELETE";
        private const string _deleteMediaMethod = "DELETE";
        private const string _deleteMediaTagMethod = "DELETE";
        private const string _deleteMediaTitleMethod = "DELETE";
        private const string _description = "description";
        private const string _featured = "featured";
        private const string _featuredMediaMethod = "GET";
        private const string _filename = "filename";
        private const string _format = "format";
        private const string _getAlbumMethod = "GET";
        private const string _getAlbumPrivacyMethod = "GET";
        private const string _getMediaDescriptionMethod = "GET";
        private const string _getMediaInformationMethod = "GET";
        private const string _getMediaLinksMethod = "GET";
        private const string _getMediaMetaDataMethod = "GET";
        private const string _getMediaTagMethod = "GET";
        private const string _getMediaTitleMethod = "GET";
        private const string _getRelatedMediaMethod = "GET";
        private const string _getUserContactsMethod = "GET";
        private const string _getUserMediaMethod = "GET";
        private const string _getUserMethod = "GET";
        private const string _getUsersMediaTagsMethod = "GET";
        private const string _getUsersUploadOptionsMethod = "GET";
        private const string _getUsersUrlMethod = "GET";
        private const string _loginTokenMethod = "POST";
        private const string _loginTokenUrl = "login/request";
        private const string _logout = "logout";
        private const string _media = "media";
        private const string _name = "name";
        private const string _num = "num";
        private const string _offset = "offset";
        private const string _page = "page";
        private const string _paginated = "paginated";
        private const string _password = "password";
        private const string _perpage = "perpage";
        private const string _photbucketUrl = "http://photobucket.com/";
        private const string _pingMethod = "POST";
        private const string _pingUrl = "ping";
        private const string _privacy = "privacy";
        private const string _recentfirst = "recentfirst";
        private const string _recurse = "recurse";
        private const string _renameAlbumMethod = "PUT";
        private const string _resizeImageMethod = "PUT";
        private const string _rotateImageMethod = "PUT";
        private const string _scramble = "scramble";
        private const string _searchMediaMethod = "GET";
        private const string _searchUrl = "search";
        private const string _secondaryperpage = "secondaryperpage";
        private const string _setMediaDescriptionMethod = "POST";
        private const string _setMediaTitleMethod = "POST";
        private const string _shareMediaViaEmailMethod = "POST";
        private const string _size = "size";
        private const string _tag = "tag";
        private const string _title = "title";
        private const string _type = "type";
        private const string _updateAlbumPrivacyMethod = "POST";
        private const string _updateMediaTagMethod = "PUT";
        private const string _updateUsersUploadOptionsMethod = "PUT";
        private const string _uploadfile = "uploadfile";
        private const string _uploadMediaMethod = "POST";
        private const string _uploadOption = "uploadoption";
        private const string _uploadUrl = "/upload";
        private const string _url = "url";
        private bool _userLoggedOn;
        private PhotobucketNet.UserToken _userToken;
        private const string _userTokenMethod = "POST";
        private const string _userTokenUrl = "login/access";
        private const string _userUrl = "user/";
        private const string _view = "view";
        private PhotobucketNet.OAuth OAuth;

        public event UploadMediaProgressHandler OnUploadMediaProgress;

        public Photobucket(string apiKey, string apiSecret) : this(apiKey, apiSecret, false)
        {
        }

        public Photobucket(string apiKey, string apiSecret, bool getLoginToken)
        {
            this._apiKey = apiKey;
            this._apiSecret = apiSecret;
            this.OAuth = new PhotobucketNet.OAuth("http://api.photobucket.com/", this._apiKey, this._apiSecret);
            if (getLoginToken)
            {
                this.RequestLoginToken();
            }
        }

        public void AddMediaTag(MediaItem mediaItem, MediaTag tag)
        {
            string relativeUrl = this.GenerateRelativeMediaTagUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("topleftx", tag.TopLeftX.ToString()));
            paramaters.Add(new QueryParameter("toplefty", tag.TopLeftY.ToString()));
            paramaters.Add(new QueryParameter("bottomrightx", tag.BottomRightX.ToString()));
            paramaters.Add(new QueryParameter("bottomrighty", tag.BottomRightY.ToString()));
            paramaters.Add(new QueryParameter("tag", tag.Name));
            if (!string.IsNullOrEmpty(tag.Contact))
            {
                paramaters.Add(new QueryParameter("contact", tag.Contact));
            }
            if (!string.IsNullOrEmpty(tag.Url))
            {
                paramaters.Add(new QueryParameter("tagurl", tag.Url));
            }
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "POST");
        }

        public void ClearUserToken()
        {
            this._userToken = null;
            this._userLoggedOn = false;
            this._currentUser = null;
        }

        public MediaItem CreateCurrentUsersImageMediaItemFromFile(string filename)
        {
            return ImageMediaItem.CreateFromFile(this.Username, filename);
        }

        public MediaItem CreateCurrentUsersMediaItemFromFile(string filename, MediaType type)
        {
            return MediaItem.CreateFromFile(this.Username, filename, type);
        }

        public MediaItem CreateCurrentUsersVideoMediaItemFromFile(string filename)
        {
            return VideoMediaItem.CreateFromFile(this.Username, filename);
        }

        private Album CreateNewAlbum(string albumName, string albumPath)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("name", albumName));
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "POST");
            return new Album(albumName, albumPath);
        }

        public Album CreateNewAlbumAtBase(string albumName)
        {
            Album baseAlbum = this.BaseAlbum;
            return this.CreateNewAlbumInAlbum(albumName, ref baseAlbum);
        }

        public Album CreateNewAlbumInAlbum(string albumName, Album album)
        {
            return this.CreateNewAlbumInAlbum(albumName, ref album);
        }

        public Album CreateNewAlbumInAlbum(string albumName, ref Album album)
        {
            Album item = this.CreateNewAlbum(albumName, album.Path);
            album.SubAlbums.Add(item);
            return item;
        }

        public void DeleteAlbum(Album album)
        {
            this.DeleteAlbum(album.Path);
        }

        private void DeleteAlbum(string albumPath)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "DELETE", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "DELETE");
        }

        public void DeleteAlbum(ref Album album)
        {
            this.DeleteAlbum(album.Path);
            album = null;
        }

        public void DeleteMedia(MediaItem mediaItem)
        {
            this.DeleteMedia(ref mediaItem);
        }

        public void DeleteMedia(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaInformationUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "DELETE", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "DELETE");
            mediaItem = null;
        }

        public void DeleteMediaDescription(MediaItem mediaItem)
        {
            this.DeleteMediaDescription(ref mediaItem);
        }

        public void DeleteMediaDescription(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaDescriptionUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "DELETE", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "DELETE");
            mediaItem.Description = string.Empty;
        }

        public void DeleteMediaTag(MediaItem mediaItem, MediaTag tag)
        {
            string relativeUrl = this.GenerateRelativeMediaTagUrl(mediaItem.Url) + "/" + tag.TagId.ToString();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "DELETE", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "DELETE");
        }

        public void DeleteMediaTitle(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaTitleUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "DELETE", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "DELETE");
            mediaItem.Title = string.Empty;
        }

        public void DeleteMediaTitle(MediaItem mediaItem)
        {
            this.DeleteMediaTitle(ref mediaItem);
        }

        private string GenerateAlbumIdentifier(string albumName)
        {
            return ("album/" + this.OAuth.UrlEncode(this.OAuth.UrlEncode(albumName)));
        }

        private string GenerateRelativeAlbumUrl(string albumName)
        {
            return this.GenerateAlbumIdentifier(albumName);
        }

        private string GenerateRelativeFeaturedUrl()
        {
            return "featured";
        }

        private string GenerateRelativeMediaDescriptionUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/description");
        }

        private string GenerateRelativeMediaInformationUrl(string url)
        {
            return this.GenerateRelativeMediaUrl(url);
        }

        private string GenerateRelativeMediaLinksUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/link");
        }

        private string GenerateRelativeMediaMetaDataUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/meta");
        }

        private string GenerateRelativeMediaTagUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/tag");
        }

        private string GenerateRelativeMediaTitleUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/title");
        }

        private string GenerateRelativeMediaUrl(string url)
        {
            return ("media/" + this.OAuth.UrlEncode(this.OAuth.UrlEncode(url)));
        }

        private string GenerateRelativeRelatedMediaUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/related");
        }

        private string GenerateRelativeResizeImageUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/size");
        }

        private string GenerateRelativeRotateImageUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/degrees");
        }

        private string GenerateRelativeSearchUrl(string query)
        {
            return ("search/" + this.OAuth.UrlEncode(query));
        }

        private string GenerateRelativeShareUrl(string url)
        {
            return (this.GenerateRelativeMediaUrl(url) + "/share");
        }

        private string GenerateRelativeUploadUrl(string albumPath)
        {
            return (this.GenerateAlbumIdentifier(albumPath) + "/upload");
        }

        private string GenerateRelativeUserMediaTagsUrl(string username)
        {
            return (this.GenerateUserUser(username) + "/tag");
        }

        private string GenerateRelativeUsersContactsUrl(string username)
        {
            return (this.GenerateUserUser(username) + "/contact");
        }

        private string GenerateRelativeUserSearchByNameUrl(string username, string mediaName)
        {
            return (this.GenerateRelativeUserSearchUrl(username) + "/" + mediaName);
        }

        private string GenerateRelativeUserSearchUrl(string username)
        {
            return (this.GenerateUserUser(username) + "/search");
        }

        private string GenerateRelativeUsersMediaWithTagUrl(string username, string tagname)
        {
            return (this.GenerateUserUser(username) + "/tag/" + tagname);
        }

        private string GenerateRelativeUsersUploadOptionsUrl()
        {
            return (this.GenerateUserUser(this.CurrentUser.Username) + "/uploadoption");
        }

        private string GenerateRelativeUsersUrlUrl(string username)
        {
            return (this.GenerateUserUser(username) + "/url");
        }

        private string GenerateRelativeUserUrl(string username)
        {
            if (string.IsNullOrEmpty(username))
            {
                return "user/";
            }
            return this.GenerateUserUser(username);
        }

        public string GenerateUserLoginUrl()
        {
            this.RequestLoginToken();
            if (!this.AppAuthorized || string.IsNullOrEmpty(this._consumerToken.NextStepUrl))
            {
                throw new PhotobucketApiException("App Not Authorized");
            }
            return (this._consumerToken.NextStepUrl + "?oauth_token=" + this._consumerToken.Token);
        }

        public string GenerateUserLogoutUrl()
        {
            return ("http://photobucket.com/apilogin/logout?oauth_consumer_key=" + this._apiKey);
        }

        private string GenerateUserUser(string username)
        {
            return ("user/" + username);
        }

        private Album GetAlbum(string albumPath)
        {
            return this.GetAlbum(albumPath, true, "nested", "all", false, 1, 20);
        }

        private Album GetAlbum(string albumPath, bool recurse, string view, string media, bool paginated, int page, int perpage)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("recurse", recurse ? "1" : "0"));
            paramaters.Add(new QueryParameter("view", view));
            paramaters.Add(new QueryParameter("media", media));
            paramaters.Add(new QueryParameter("paginated", paginated ? "1" : "0"));
            paramaters.Add(new QueryParameter("page", page.ToString()));
            paramaters.Add(new QueryParameter("perpage", perpage.ToString()));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return new Album(this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml.SelectSingleNode("descendant::album"));
        }

        public Privacy GetAlbumsPrivacySettings(Album album)
        {
            return this.GetAlbumsPrivacySettings(ref album);
        }

        public Privacy GetAlbumsPrivacySettings(ref Album album)
        {
            album.Privacy = this.GetAlbumsPrivacySettings(album.Path);
            return album.Privacy;
        }

        private Privacy GetAlbumsPrivacySettings(string albumPath)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            return this.GetPrivacyFromResponseMessage(xmlResponseMessageFromUrl);
        }

        public AlbumList GetAllCurrentUsersAlbums()
        {
            return this.GetAllUsersAlbums(this.CurrentUser.Username);
        }

        public MediaItemList GetAllCurrentUsersImageMedia()
        {
            this._currentUser = this.CurrentUser;
            return this.GetAllUsersImageMedia(ref this._currentUser);
        }

        public MediaItemList GetAllCurrentUsersMedia()
        {
            this._currentUser = this.CurrentUser;
            return this.GetAllUsersMedia(ref this._currentUser);
        }

        public MediaItemList GetAllCurrentUsersMediaWithTag(MediaTag mediaTag)
        {
            return this.GetAllUsersMediaWithTag(this.CurrentUser.Username, mediaTag);
        }

        public MediaItemList GetAllCurrentUsersVideoMedia()
        {
            this._currentUser = this.CurrentUser;
            return this.GetAllUsersVideoMedia(ref this._currentUser);
        }

        public AlbumList GetAllUsersAlbums(string username)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("recurse", "1"));
            paramaters.Add(new QueryParameter("view", "flat"));
            paramaters.Add(new QueryParameter("media", "none"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return AlbumList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public MediaItemList GetAllUsersImageMedia(string username)
        {
            return this.GetAllUsersMedia(username, MediaType.Image);
        }

        public MediaItemList GetAllUsersImageMedia(ref User user)
        {
            user.SetImageMediaList = this.GetAllUsersImageMedia(user.Username);
            return user.ImageMediaList;
        }

        public MediaItemList GetAllUsersMedia(string username)
        {
            return this.GetAllUsersMedia(username, MediaType.All);
        }

        public MediaItemList GetAllUsersMedia(ref User user)
        {
            user.SetMediaList = this.GetAllUsersMedia(user.Username);
            return user.MediaList;
        }

        public MediaItemList GetAllUsersMedia(string username, MediaType type)
        {
            return this.GetAllUsersMedia(username, type, 200);
        }

        public MediaItemList GetAllUsersMedia(string username, MediaType type, int perPage)
        {
            MediaItemList list = new MediaItemList();
            int page = 0;
            bool flag = true;
            while (flag)
            {
                page++;
                MediaItemList collection = this.GetUsersRecentMedia(username, type, page, perPage);
                list.AddRange(collection);
                if (collection.Count < perPage)
                {
                    flag = false;
                }
            }
            return list;
        }

        public MediaItemList GetAllUsersMediaWithTag(string username, MediaTag mediaTag)
        {
            MediaItemList list = new MediaItemList();
            int page = 0;
            bool flag = true;
            while (flag)
            {
                page++;
                MediaItemList collection = this.GetUsersMediaWithTag(username, mediaTag.Name, page, 200);
                list.AddRange(collection);
                if (collection.Count < 200)
                {
                    flag = false;
                }
            }
            return list;
        }

        public MediaItemList GetAllUsersVideoMedia(string username)
        {
            return this.GetAllUsersMedia(username, MediaType.Video);
        }

        public MediaItemList GetAllUsersVideoMedia(ref User user)
        {
            user.SetVideoMediaList = this.GetAllUsersVideoMedia(user.Username);
            return user.VideoMediaList;
        }

        public Privacy GetBaseAlbumsPrivacySettings()
        {
            Album baseAlbum = this.BaseAlbum;
            return this.GetAlbumsPrivacySettings(ref baseAlbum);
        }

        public User GetCurrentUser()
        {
            this._currentUser = this.GetUser(this.Username);
            return this._currentUser;
        }

        public Album GetCurrentUsersAlbum(string albumPath)
        {
            return this.GetUsersAlbum(this.CurrentUser.Username, albumPath);
        }

        public Album GetCurrentUsersAlbum(string albumPath, bool recurse, string view, string media, bool paginated, int page, int perpage)
        {
            return this.GetUsersAlbum(this.CurrentUser.Username, albumPath, recurse, view, media, paginated, page, perpage);
        }

        public Album GetCurrentUsersBaseAlbum()
        {
            this._currentUser.SetAlbum = this.GetUsersBaseAlbum(this.CurrentUser.Username);
            return this._currentUser.Album;
        }

        public Album GetCurrentUsersBaseAlbum(bool recurse, string view, string media, bool paginated, int page, int perpage)
        {
            this._currentUser.SetAlbum = this.GetUsersBaseAlbum(this.CurrentUser.Username, recurse, view, media, paginated, page, perpage);
            return this._currentUser.Album;
        }

        public UserContactList GetCurrentUsersContacts()
        {
            string relativeUrl = this.GenerateRelativeUsersContactsUrl(this._currentUser.Username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            this._currentUser.SetContact = UserContactList.CreateFromXmlResponseMessage(xmlResponseMessageFromUrl);
            return this._currentUser.Contacts;
        }

        public MediaTagList GetCurrentUsersMediaTags()
        {
            this._currentUser.SetMediaTags = this.GetUsersMediaTags(this.CurrentUser.Username);
            return this._currentUser.MediaTags;
        }

        public MediaItemList GetCurrentUsersRecentMedia(MediaType type, int page, int perPage)
        {
            return this.GetUsersRecentMedia(this.CurrentUser.Username, type, page, perPage);
        }

        public UploadOptions GetCurrentUsersUploadOptions()
        {
            string relativeUrl = this.GenerateRelativeUsersUploadOptionsUrl();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            this.CurrentUser.SetUploadOptions = UploadOptions.CreateFromXmlResponseMessage(xmlResponseMessageFromUrl);
            return this.CurrentUser.UploadOptions;
        }

        public UserUrls GetCurrentUsersUrls()
        {
            this.CurrentUser.SetUserUrls = this.GetUsersUrls(this.CurrentUser.Username);
            return this._currentUser.UserUrls;
        }

        public MediaItemList GetFeaturedMedia()
        {
            string relativeUrl = this.GenerateRelativeFeaturedUrl();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL("http://api.photobucket.com/", relativeUrl, "GET", this.Token, paramaters);
            return MediaItemList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public string GetMediaDescription(MediaItem mediaItem)
        {
            return this.GetMediaDescription(ref mediaItem);
        }

        public string GetMediaDescription(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaDescriptionUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlNode node = this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml.SelectSingleNode("descendant::description");
            mediaItem.Description = node.InnerText;
            return mediaItem.Description;
        }

        public MediaItem GetMediaInformation(MediaItem mediaItem)
        {
            return this.GetMediaInformation(ref mediaItem);
        }

        public MediaItem GetMediaInformation(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaInformationUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            mediaItem = MediaItem.CreateFromXmlNode(mediaItem.MediaType, xmlResponseMessageFromUrl.ResponseXml.SelectSingleNode("descendant::media"));
            return mediaItem;
        }

        private XmlDocument GetMediaLinks(MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaLinksUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml;
        }

        public MetaData GetMediaMetaData(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaMetaDataUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            mediaItem.SetMetaData = MetaData.CreateFromXmlResponseMessage(xmlResponseMessageFromUrl);
            return mediaItem.MetaData;
        }

        public MetaData GetMediaMetaData(MediaItem mediaItem)
        {
            return this.GetMediaMetaData(ref mediaItem);
        }

        public string GetMediaShareTagLink(MediaItem mediaItem)
        {
            return this.GetMediaLinks(mediaItem).SelectSingleNode("descendant::sharetag").InnerText.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace("&amp;", "&");
        }

        public MediaTag GetMediaTag(MediaItem mediaItem, int tagId)
        {
            string relativeUrl = this.GenerateRelativeMediaTagUrl(mediaItem.Url) + "/" + tagId.ToString();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return MediaTag.CreateFromXmlNode(this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml.SelectSingleNode("descendant::content"));
        }

        public MediaTagList GetMediaTags(MediaItem mediaItem)
        {
            return this.GetMediaTags(ref mediaItem);
        }

        public MediaTagList GetMediaTags(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaTagUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "GET");
            mediaItem.SetMediaTags = MediaTagList.CreateFromXmlResponseMessage(xmlResponseMessageFromUrl);
            return mediaItem.MediaTags;
        }

        public string GetMediaTitle(MediaItem mediaItem)
        {
            return this.GetMediaTitle(ref mediaItem);
        }

        public string GetMediaTitle(ref MediaItem mediaItem)
        {
            string relativeUrl = this.GenerateRelativeMediaTitleUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            XmlNode node = this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml.SelectSingleNode("descendant::title");
            mediaItem.Title = node.InnerText;
            return mediaItem.Title;
        }

        private Privacy GetPrivacyFromResponseMessage(XmlResponseMessage responseMessage)
        {
            XmlNode node = responseMessage.ResponseXml.SelectSingleNode("descendant::content");
            if (node == null)
            {
                throw new PhotobucketApiException("Did not find content in xml response from GetAlbumPrivacySettigns");
            }
            if (node.InnerText == "public")
            {
                return Privacy.PUBLIC;
            }
            if (node.InnerText != "private")
            {
                throw new PhotobucketApiException("Did not see public or private for privacy settings");
            }
            return Privacy.PRIVATE;
        }

        public MediaItemList GetRelatedMedia(MediaItem mediaItem, int num, MediaType mediaType)
        {
            string relativeUrl = this.GenerateRelativeRelatedMediaUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("num", num.ToString()));
            string str2 = (mediaType == MediaType.Image) ? "images" : "videos";
            paramaters.Add(new QueryParameter("type", str2));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return MediaItemList.CreateFromXmlNodeList(this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml.SelectNodes("descendant::media"));
        }

        private XmlResponseMessage GetResponseForUploadMediaItem(string uploadMediaItemUrl, MediaItem mediaItem, QueryParameterList paramaters)
        {
            XmlResponseMessage message;
            string str = "PHOTBUCKET_MIME_" + DateTime.Now.ToString("yyyyMMddhhmmss");
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uploadMediaItemUrl);
            request.UserAgent = "Mozilla/4.0 PhotobucketNet API (compatible; MSIE 6.0; Windows NT 5.1)";
            request.Method = "POST";
            request.KeepAlive = true;
            request.ContentType = "multipart/form-data; boundary=" + str;
            request.Expect = "";
            StringBuilder builder = new StringBuilder();
            foreach (QueryParameter parameter in paramaters)
            {
                if (parameter.Name == "format")
                {
                    continue;
                }
                if (parameter.Name == "oauth_signature")
                {
                    parameter.Value = this.OAuth.UrlDecode(parameter.Value);
                }
                else if ((parameter.Name == "description") || (parameter.Name == "title"))
                {
                    parameter.Value = this.OAuth.UrlDecode(parameter.Value);
                }
                builder.Append("--" + str + "\r\n");
                builder.Append("Content-Disposition: form-data; name=\"" + parameter.Name + "\"\r\n");
                builder.Append("\r\n");
                builder.Append(parameter.Value + "\r\n");
            }
            builder.Append("--" + str + "\r\n");
            builder.Append("Content-Disposition: form-data; name=\"uploadfile\"; filename=\"" + mediaItem.Name + "\"\r\n");
            builder.Append("Content-Type: mimetype\r\nContent-Transfer-Ecoding: binary");
            builder.Append("\r\n\r\n");
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] bytes = encoding.GetBytes(builder.ToString());
            Stream mediaStream = mediaItem.MediaStream;
            byte[] buffer = new byte[mediaStream.Length];
            mediaStream.Read(buffer, 0, buffer.Length);
            mediaStream.Close();
            byte[] src = encoding.GetBytes("\r\n--" + str + "--\r\n");
            byte[] dst = new byte[(bytes.Length + buffer.Length) + src.Length];
            System.Buffer.BlockCopy(bytes, 0, dst, 0, bytes.Length);
            System.Buffer.BlockCopy(buffer, 0, dst, bytes.Length, buffer.Length);
            System.Buffer.BlockCopy(src, 0, dst, bytes.Length + buffer.Length, src.Length);
            request.ContentLength = dst.Length;
            Stream requestStream = request.GetRequestStream();
            int num = 1;
            int num2 = Math.Max(dst.Length / 100, 0xc800);
            int dataSent = 0;
            if (this.OnUploadMediaProgress != null)
            {
                this.OnUploadMediaProgress(this, new UploadMediaProgressEventArgs(0, dst.Length));
            }
            for (int i = 0; i < dst.Length; i += num2)
            {
                int count = Math.Min(num2, dst.Length - i);
                dataSent += count;
                requestStream.Write(dst, i, count);
                if ((this.OnUploadMediaProgress != null) && (((num++ % 5) == 0) || (dataSent == dst.Length)))
                {
                    this.OnUploadMediaProgress(this, new UploadMediaProgressEventArgs(dataSent, dst.Length));
                }
            }
            requestStream.Close();
            try
            {
                request.Method = "POST";
                HttpWebResponse response = (HttpWebResponse) request.GetResponse();
                message = new XmlResponseMessage(response.GetResponseStream());
            }
            catch (WebException exception)
            {
                throw PhotobucketException.CreateFromWebException(exception);
            }
            return message;
        }

        private ResponseMessage GetResponseMessageFromUrl(string url, string method)
        {
            return new ResponseMessage(this.GetResponseStreamFromUrl(url, method));
        }

        private Stream GetResponseStreamFromUrl(string url, string method)
        {
            Stream responseStream;
            try
            {
                WebRequest request = WebRequest.Create(url);
                request.Method = method;
                request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
                responseStream = request.GetResponse().GetResponseStream();
            }
            catch (WebException exception)
            {
                throw PhotobucketException.CreateFromWebException(exception);
            }
            return responseStream;
        }

        private User GetUser(string username)
        {
            string relativeUrl = this.GenerateRelativeUserUrl(username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return new User(this.GetXmlResponseMessageFromUrl(url, "GET").ResponseXml);
        }

        public Album GetUsersAlbum(string username, string albumPath)
        {
            albumPath = string.IsNullOrEmpty(albumPath) ? "" : ("/" + albumPath);
            return this.GetAlbum(username + albumPath, true, "nested", "all", false, 1, 20);
        }

        public Album GetUsersAlbum(string username, string albumPath, bool recurse, string view, string media, bool paginated, int page, int perpage)
        {
            albumPath = string.IsNullOrEmpty(albumPath) ? "" : ("/" + albumPath);
            return this.GetAlbum(username + albumPath, recurse, view, media, paginated, page, perpage);
        }

        public Album GetUsersBaseAlbum(string username)
        {
            return this.GetUsersAlbum(username, string.Empty);
        }

        public Album GetUsersBaseAlbum(string username, bool recurse, string view, string media, bool paginated, int page, int perpage)
        {
            return this.GetUsersAlbum(username, string.Empty, recurse, view, media, paginated, page, perpage);
        }

        public MediaTagList GetUsersMediaTags(string username)
        {
            string relativeUrl = this.GenerateRelativeUserMediaTagsUrl(username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return MediaTagList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public MediaItemList GetUsersMediaWithTag(string username, string tagname)
        {
            return this.GetUsersMediaWithTag(username, tagname, 1, 200);
        }

        public MediaItemList GetUsersMediaWithTag(string username, string tagname, int page, int perPage)
        {
            if (string.IsNullOrEmpty(tagname))
            {
                throw new PhotobucketApiException("tagname is null");
            }
            string relativeUrl = this.GenerateRelativeUsersMediaWithTagUrl(username, tagname);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("page", page.ToString()));
            paramaters.Add(new QueryParameter("perpage", perPage.ToString()));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return MediaItemList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public MediaItemList GetUsersRecentMedia(string username, MediaType type, int page, int perPage)
        {
            string relativeUrl = this.GenerateRelativeUserSearchUrl(username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("type", type.ToString().ToLower()));
            paramaters.Add(new QueryParameter("page", page.ToString()));
            paramaters.Add(new QueryParameter("perpage", perPage.ToString()));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return MediaItemList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public UserUrls GetUsersUrls(string username)
        {
            string relativeUrl = this.GenerateRelativeUserUrl(username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "GET", this.Token, paramaters);
            return UserUrls.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        private XmlResponseMessage GetXmlResponseMessageFromUrl(string url, string method)
        {
            return new XmlResponseMessage(this.GetResponseStreamFromUrl(url, method));
        }

        public void LaunchUserLogin()
        {
            try
            {
                Process.Start(this.GenerateUserLoginUrl());
            }
            catch (Exception)
            {
                throw new PhotobucketApiException("Trouble launching login url");
            }
        }

        public void LaunchUserLogout()
        {
            try
            {
                Process.Start(this.GenerateUserLogoutUrl());
                this.ClearUserToken();
            }
            catch (Exception)
            {
                throw new PhotobucketApiException("Trouble launching login url");
            }
        }

        public Privacy MakeAlbumPrivate(ref Album album, string password)
        {
            return this.UpdateAlbumPrivacySettings(ref album, Privacy.PRIVATE, password);
        }

        public Privacy MakeAlbumPrivate(Album album, string password)
        {
            return this.UpdateAlbumPrivacySettings(album, Privacy.PRIVATE, password);
        }

        public Privacy MakeAlbumPublic(Album album)
        {
            return this.UpdateAlbumPrivacySettings(album, Privacy.PUBLIC, "");
        }

        public Privacy MakeAlbumPublic(ref Album album)
        {
            return this.UpdateAlbumPrivacySettings(ref album, Privacy.PUBLIC, "");
        }

        public Privacy MakeBaseAlbumPrivate(string password)
        {
            Album baseAlbum = this.BaseAlbum;
            return this.MakeAlbumPrivate(ref baseAlbum, password);
        }

        public Privacy MakeBaseAlbumPublic()
        {
            Album baseAlbum = this.BaseAlbum;
            return this.MakeAlbumPublic(ref baseAlbum);
        }

        public void Ping()
        {
            string url = this.OAuth.GenerateURL(this.ApiUrl, "ping", "POST", new PhotobucketToken());
            this.GetResponseMessageFromUrl(url, "POST");
        }

        public void RenameAlbum(ref Album album, string newAlbumName)
        {
            this.RenameAlbum(album.Name, newAlbumName);
            album.Name = newAlbumName;
        }

        public void RenameAlbum(Album album, string newAlbumName)
        {
            this.RenameAlbum(ref album, newAlbumName);
        }

        private void RenameAlbum(string origAlbumPath, string newAlbumName)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(origAlbumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("name", newAlbumName));
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "PUT", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "PUT");
        }

        private void RequestLoginToken()
        {
            string url = this.OAuth.GenerateURL(this.ApiUrl, "login/request", "POST", new PhotobucketToken());
            ResponseMessage responseMessageFromUrl = this.GetResponseMessageFromUrl(url, "POST");
            this._consumerToken = this.OAuth.GetConsumerTokenFromResponse(responseMessageFromUrl.ResponseString);
            this._appAuthorized = true;
        }

        public PhotobucketNet.UserToken RequestUserToken()
        {
            if (!this.AppAuthorized)
            {
                throw new PhotobucketApiException("App Not Authorized");
            }
            string url = this.OAuth.GenerateURL("http://api.photobucket.com/", "login/access", "POST", this._consumerToken);
            ResponseMessage responseMessageFromUrl = this.GetResponseMessageFromUrl(url, "POST");
            this._userToken = this.OAuth.GetUserTokenFromResponse(responseMessageFromUrl.ResponseString);
            this._userLoggedOn = true;
            this._appAuthorized = false;
            this._consumerToken = null;
            this._currentUser = new User(this._userToken.Username);
            return this._userToken;
        }

        public void ResizeImage(MediaItem mediaItem, ImageSize newSize)
        {
            string relativeUrl = this.GenerateRelativeResizeImageUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "PUT", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "PUT");
        }

        public void RotateImage(MediaItem mediaItem, int degrees)
        {
            string relativeUrl = this.GenerateRelativeRotateImageUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "PUT", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "PUT");
        }

        public MediaItemList SearchMedia(string query)
        {
            return this.SearchMedia(query, 20, 20, 1, 0, 5, "images", false);
        }

        public MediaItemList SearchMedia(string query, int num, int perpage, int page, int offset, int secondaryperpage, string type, bool recentFirst)
        {
            string relativeUrl = this.GenerateRelativeSearchUrl(query);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("num", num.ToString()));
            paramaters.Add(new QueryParameter("perpage", perpage.ToString()));
            paramaters.Add(new QueryParameter("page", page.ToString()));
            paramaters.Add(new QueryParameter("offset", offset.ToString()));
            paramaters.Add(new QueryParameter("secondaryperpage", secondaryperpage.ToString()));
            paramaters.Add(new QueryParameter("type", type));
            paramaters.Add(new QueryParameter("recentfirst", recentFirst ? "1" : "0"));
            string url = this.OAuth.GenerateURL("http://api.photobucket.com/", relativeUrl, "GET", this.Token, paramaters);
            return MediaItemList.CreateFromXmlResponseMessage(this.GetXmlResponseMessageFromUrl(url, "GET"));
        }

        public void SetMediaDescription(ref MediaItem mediaItem, string description)
        {
            string relativeUrl = this.GenerateRelativeMediaDescriptionUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("description", description));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "POST");
            mediaItem.Description = description;
        }

        public void SetMediaDescription(MediaItem mediaItem, string description)
        {
            this.SetMediaDescription(ref mediaItem, description);
        }

        public void SetMediaTitle(ref MediaItem mediaItem, string title)
        {
            string relativeUrl = this.GenerateRelativeMediaTitleUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("title", title));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "POST");
            mediaItem.Title = title;
        }

        public void SetMediaTitle(MediaItem mediaItem, string title)
        {
            this.SetMediaTitle(ref mediaItem, title);
        }

        public void ShareMediaViaEmail(MediaItem mediaItem, string email, string body)
        {
            string relativeUrl = this.GenerateRelativeShareUrl(mediaItem.Url);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("body", body));
            paramaters.Add(new QueryParameter("email", email));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "POST");
        }

        public Privacy UpdateAlbumPrivacySettings(Album album, Privacy privacySetting, string password)
        {
            return this.UpdateAlbumPrivacySettings(ref album, privacySetting, password);
        }

        public Privacy UpdateAlbumPrivacySettings(ref Album album, Privacy privacySetting, string password)
        {
            album.Privacy = this.UpdateAlbumPrivacySettings(album.Path, privacySetting, password);
            return album.Privacy;
        }

        private Privacy UpdateAlbumPrivacySettings(string albumPath, Privacy privacySetting, string password)
        {
            string relativeUrl = this.GenerateRelativeAlbumUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            if (privacySetting == Privacy.PUBLIC)
            {
                paramaters.Add(new QueryParameter("privacy", "public"));
            }
            else
            {
                paramaters.Add(new QueryParameter("privacy", "private"));
                paramaters.Add(new QueryParameter("password", password));
            }
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "POST", this.Token, paramaters);
            XmlResponseMessage xmlResponseMessageFromUrl = this.GetXmlResponseMessageFromUrl(url, "POST");
            return this.GetPrivacyFromResponseMessage(xmlResponseMessageFromUrl);
        }

        public UploadOptions UpdateCurrentUsersUploadOptions(ImageSize imageSize, bool autoTagging)
        {
            string relativeUrl = this.GenerateRelativeUsersUploadOptionsUrl();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("defaultimagesize", Convert.ToString(imageSize)));
            paramaters.Add(new QueryParameter("autotagging", autoTagging ? "1" : "0"));
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "PUT", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "PUT");
            UploadOptions options = new UploadOptions();
            options.SetDefaultImageSize = imageSize;
            options.SetAutoTagging = autoTagging;
            this.CurrentUser.SetUploadOptions = options;
            return this._currentUser.UploadOptions;
        }

        public void UpdateMediaTag(MediaItem mediaItem, MediaTag tag)
        {
            string relativeUrl = this.GenerateRelativeMediaTagUrl(mediaItem.Url) + "/" + tag.TagId.ToString();
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            if (tag.TopLeftX == -1f)
            {
                paramaters.Add(new QueryParameter("topleftx", tag.TopLeftX.ToString()));
            }
            if (tag.TopLeftY == -1f)
            {
                paramaters.Add(new QueryParameter("toplefty", tag.TopLeftY.ToString()));
            }
            if (tag.BottomRightX == -1f)
            {
                paramaters.Add(new QueryParameter("bottomrightx", tag.BottomRightX.ToString()));
            }
            if (tag.BottomRightY == -1f)
            {
                paramaters.Add(new QueryParameter("bottomrighty", tag.BottomRightY.ToString()));
            }
            if (!string.IsNullOrEmpty(tag.Name))
            {
                paramaters.Add(new QueryParameter("tag", tag.Name));
            }
            if (!string.IsNullOrEmpty(tag.Contact))
            {
                paramaters.Add(new QueryParameter("contact", tag.Contact));
            }
            if (!string.IsNullOrEmpty(tag.Url))
            {
                paramaters.Add(new QueryParameter("tagurl", tag.Url));
            }
            string url = this.OAuth.GenerateURL(this.ApiUrl, relativeUrl, "PUT", this.Token, paramaters);
            this.GetXmlResponseMessageFromUrl(url, "PUT");
        }

        public MediaItem UploadMediaItemToAlbum(MediaItem mediaItem, Album album)
        {
            return this.UploadMediaItemToAlbum(mediaItem, album.Path);
        }

        public MediaItem UploadMediaItemToAlbum(MediaItem mediaItem, ref Album album)
        {
            MediaItem item = this.UploadMediaItemToAlbum(mediaItem, album.Path);
            album.MediaList.Add(item);
            return item;
        }

        private MediaItem UploadMediaItemToAlbum(MediaItem mediaItem, string albumPath)
        {
            string relativeUrl = this.GenerateRelativeUploadUrl(albumPath);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            paramaters.Add(new QueryParameter("type", mediaItem.Type));
            if (!string.IsNullOrEmpty(mediaItem.Description))
            {
                paramaters.Add(new QueryParameter("description", this.OAuth.UrlEncode(mediaItem.Description)));
            }
            if (!string.IsNullOrEmpty(mediaItem.Title))
            {
                paramaters.Add(new QueryParameter("title", this.OAuth.UrlEncode(mediaItem.Title)));
            }
            QueryParameterList list2 = this.OAuth.GenerateOAuthParamaters(relativeUrl, "POST", this.Token, paramaters);
            string uploadMediaItemUrl = this.ApiUrl + relativeUrl + "?format=xml";
            MediaItem item = new MediaItem(this.GetResponseForUploadMediaItem(uploadMediaItemUrl, mediaItem, list2).ResponseXml);
            this._currentUser.MediaList.Add(item);
            return item;
        }

        public MediaItem UploadMediaItemToBaseAlbum(MediaItem mediaItem)
        {
            Album baseAlbum = this.BaseAlbum;
            return this.UploadMediaItemToAlbum(mediaItem, ref baseAlbum);
        }

        public bool ValidateCurrentUserToken()
        {
            return this.ValidateUserToken(this.UserToken);
        }

        public bool ValidateUserToken(PhotobucketNet.UserToken userToken)
        {
            string relativeUrl = this.GenerateRelativeUserUrl(userToken.Username);
            QueryParameterList paramaters = new QueryParameterList();
            paramaters.Add(new QueryParameter("format", "xml"));
            string url = this.OAuth.GenerateURL(userToken.UserApi, relativeUrl, "GET", userToken, paramaters);
            try
            {
                this.GetXmlResponseMessageFromUrl(url, "GET");
                return true;
            }
            catch (PhotobucketApiException exception)
            {
                if (exception.ErrorCode != ErrorCode.CouldNotGet)
                {
                    throw;
                }
                return false;
            }
        }

        public string ApiUrl
        {
            get
            {
                if (this.UserLoggedOn)
                {
                    return this._userToken.UserApi;
                }
                return "http://api.photobucket.com/";
            }
        }

        public bool AppAuthorized
        {
            get
            {
                return (this._appAuthorized && (this._consumerToken != null));
            }
        }

        public Album BaseAlbum
        {
            get
            {
                if (this._currentUser.Album == null)
                {
                    this.GetCurrentUsersBaseAlbum();
                }
                return this._currentUser.Album;
            }
        }

        public User CurrentUser
        {
            get
            {
                if (this._currentUser == null)
                {
                    this.GetCurrentUser();
                }
                return this._currentUser;
            }
        }

        private PhotobucketToken Token
        {
            get
            {
                if (this.UserLoggedOn)
                {
                    return this._userToken;
                }
                if (!this.AppAuthorized)
                {
                    this.RequestLoginToken();
                }
                return this._consumerToken;
            }
        }

        public bool UserLoggedOn
        {
            get
            {
                return (this._userLoggedOn && (this._userToken != null));
            }
        }

        public string Username
        {
            get
            {
                if (!this.UserLoggedOn)
                {
                    throw new PhotobucketApiException("User not logged on");
                }
                return this._userToken.Username;
            }
        }

        public PhotobucketNet.UserToken UserToken
        {
            get
            {
                if (!this.UserLoggedOn)
                {
                    throw new PhotobucketApiException("Token Not Authorized");
                }
                return this._userToken;
            }
            set
            {
                if (!value.Equals(new PhotobucketNet.UserToken()))
                {
                    this._userToken = value;
                    this._userLoggedOn = true;
                    this._appAuthorized = false;
                    this._consumerToken = null;
                    this._currentUser = new User(this._userToken.Username);
                }
            }
        }

        public delegate void UploadMediaProgressHandler(object sender, UploadMediaProgressEventArgs eventArgs);
    }
}

